/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "reader_proxy.h"

#include "common_utils.h"
#include "isecure_element_session.h"
#include "loghelper.h"
#include "message_option.h"
#include "message_parcel.h"
#include "se_service_ipc_interface_code.h"
#include "session_proxy.h"

namespace OHOS {
namespace SE {
namespace OMAPI {
ErrorCode ReaderProxy::IsSecureElementPresent(bool &isPresent)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    isPresent = false;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("IsSecureElementPresent Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int32_t res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_READER_IS_SE_PRESENT),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ReaderProxy::IsSecureElementPresent] send request(%{public}d) with Res(%{public}d) fail",
            SeServiceIpcInterfaceCode::COMMAND_READER_IS_SE_PRESENT, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ReaderProxy::IsSecureElementPresent] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_READER_IS_SE_PRESENT, res);
    isPresent = reply.ReadBool();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ReaderProxy::OpenSession(sptr<ISecureElementSession> &session)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("OpenSession Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int32_t res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_READER_OPEN_SESSION),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ReaderProxy::OpenSession] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_READER_OPEN_SESSION, res);
        session = nullptr;
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }

    sptr<OHOS::IRemoteObject> object = reply.ReadRemoteObject();
    int statusCode = reply.ReadInt32();
    if (object == nullptr) {
        ErrorLog("[ReaderProxy::OpenSession] send request(%{public}d) with State(%{public}d) fail. "
            "IRemoteObject is empty.",
            SeServiceIpcInterfaceCode::COMMAND_READER_OPEN_SESSION, statusCode);
        session = nullptr;
    } else {
        InfoLog("[ReaderProxy::OpenSession] send request(%{public}d) with Res(%{public}d) success.",
            SeServiceIpcInterfaceCode::COMMAND_READER_OPEN_SESSION, res);
        if (!session) {
            InfoLog("OpenSession new session");
            session = new SessionProxy(object);
        } else {
            ErrorLog("OpenSession new session before not null error");
        }
    }
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ReaderProxy::CloseSessions(void)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("CloseSessions Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int32_t res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_READER_CLOSE_SESSIONS),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ReaderProxy::CloseSessions] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_READER_CLOSE_SESSIONS, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ReaderProxy::Reset(bool &resetStatus)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    resetStatus = false;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("Reset Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int32_t res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_READER_RESET),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ReaderProxy::Reset] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_READER_RESET, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ReaderProxy::Reset] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_READER_RESET, res);
    resetStatus = reply.ReadBool();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}
}  // namespace OMAPI
}  // namespace SE
}  // namespace OHOS